/*****************************************************************************
  Copyright ?2002-2004 by Martin Cook. All rights are reserved. If you like
  this code then feel free to go ahead and use it. The only thing I ask is 
  that you don't remove or alter my copyright notice. Your use of this 
  software is entirely at your own risk. I make no claims about the 
  reliability or fitness of this code for any particular purpose. If you 
  make changes or additions to this code then please clearly mark your code 
  as yours. If you have questions or comments then please contact me at: 
  martin@codegator.com
  
  Have Fun! :o)
*****************************************************************************/


using System;
using System.Data;
using System.Security.Principal;

namespace CG.Security.Principal
{

	/// <summary>
	/// A custom identity with support for CG.Security features.
	/// </summary>
	public sealed class CustomIdentity : System.Security.Principal.IIdentity
	{

		// ******************************************************************
		// Attributes.
		// ******************************************************************

		#region Attributes

		/// <summary>
		/// The user name.
		/// </summary>
		private string m_name;

		/// <summary>
		/// The user database identifier.
		/// </summary>
		private int m_userID;

		/// <summary>
		/// The date the user was created in the database.
		/// </summary>
		private DateTime m_createDate;

		/// <summary>
		/// The last date/time the user was authenticated.
		/// </summary>
		private DateTime m_lastLogin;

		#endregion

		// ******************************************************************
		// Properties.
		// ******************************************************************

		#region Properties

		/// <summary>
		/// Gets the user datbase identifier.
		/// </summary>
		public int UserID
		{
			get {return m_userID;}
		} // End UserID

		// ******************************************************************

		/// <summary>
		/// Gets the date the user was created in the database.
		/// </summary>
		public DateTime CreateDate
		{
			get {return m_createDate;}
		} // End CreateDate

		// ******************************************************************

		/// <summary>
		/// Gets the last date/time the user was authenticated.
		/// </summary>
		public DateTime LastLogin
		{
			get {return m_lastLogin;}
		} // End LastLogin()

		#endregion

		// ******************************************************************
		// Constructors.
		// ******************************************************************

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the GenericIdentity class representing the user with the specified name.
		/// </summary>
		/// <param name="name"></param>
		public CustomIdentity(
			string name
			)
		{

			// Sanity check the name before using it.
			if (name == null)
				throw new ArgumentNullException(
					"name",
					"Argument must not be null"
					);

			m_name = name;

			IDataReader reader = null;

			try
			{

				// Find the user in the database.
				reader = UserManager.FindByUserName(
					name
					);

				// Sanity check the reader before using it.
				if (reader == null || !reader.Read())
					throw new SecurityException(
						"User " + name + " does not exist in the database!"
						);
				
				// Copy the user properties.
				m_userID = (Int32)reader["user_id"];
				m_createDate = (DateTime)reader["create_date"];

				if (reader.IsDBNull(reader.GetOrdinal("last_login")))
					m_lastLogin = DateTime.MinValue;
				else
					m_lastLogin = (DateTime)reader["last_login"];

			} // End try

			finally
			{

				// Should we cleanup the reader?
				if (reader != null)
					reader.Close();

			} // End finally

		} // End CustomIdentity()

		#endregion 

		// ******************************************************************
		// IIdentity implementation.
		// ******************************************************************

		#region IIdentity implementation

		/// <summary>
		/// Gets a value that indicates whether the user has been authenticated.
		/// </summary>
		public bool IsAuthenticated
		{
			get {return true;}		
		} // End IsAuthenticated

		// ******************************************************************

		/// <summary>
		/// Gets the type of authentication used.
		/// </summary>
		public string AuthenticationType
		{
			get {return "Custom";}
		} // End AuthenticationType

		// ******************************************************************

		/// <summary>
		/// Gets the name of the current user.
		/// </summary>
		public string Name
		{
			get {return m_name;}
		} // End Name

		#endregion

	} // End class CustomIdentity

} // End namespace CG.Security.Principal

